#include "Win.hpp"

namespace mi
{
    Win::Win (std::string title, bool isMovable) :
        Widget(tWindow, title)
    {
        titlebarHeight = 30;
        SetSize(Vec2i(400,300));
        SetPos(Vec2i(0,0));
        move = false;
        movable = isMovable;
        resize = false;
        resizeAreaSize = titlebarHeight;
        minSize = Vec2i(100,50);
        
        mainView.SetPos(position);
        mainView.SetSize(size);

        if (resizeTexture == NULL)
        {
          resizeTexture = new sf::Texture();
          resizeTexture->loadFromFile("./resources/textures/ui/widget/resizeTexture.png");
        }

        this->title.setString(title);
        this->title.setFont(Widget::defaultFont);
        this->title.setCharacterSize(Widget::defaultFontSize);
    }

    bool Win::Movable()
    {
        return movable;
    }

    bool Win::Movable(bool isMovable)
    {
        bool oldval = movable;
        movable = isMovable;
        return oldval;
    }

    bool Win::Contains(Widget *other)
    {
        bool res = mainView.Contains(other);

        return res || (other == this);
    }


    Widget* Win::MouseClick(sf::Mouse::Button button, sf::MouseState state, int x, int y)
    {
        if (IsMouseInResizeArea(x,y))
        {
            if (state == sf::Down)
            {
                resize = true;
            }
            move = false;
            return this;
        }
        else if (IsMouseInTitlebar(x,y))
        {
            if (state == sf::Down)
            {
                move = true;
            }
            resize = false;
            return this;
        }
        else
        {
          move = false;
          resize = false;
        }

        Widget *res = mainView.MouseClick(button, state, x, y);
        if (res != NULL)
            return res;

        if (IsMouseInBody(Vec2i( x, y)))
            return this;

        return NULL;
    }

    Widget* Win::MouseMoved(int x, int y, int dx, int dy)
    {
        Widget *res = mainView.MouseMoved(x, y, dx, dy);
        if (res != NULL)
            return res;
        if (IsMouseInBody(Vec2i(x,y)) || IsMouseInTitlebar(x,y) )
            return this;
        return NULL;
    }

    Widget* Win::MouseDragged(int x, int y, int dx, int dy)
    {
        Widget *res = mainView.MouseDragged(x, y, dx, dy);
        if (res != NULL)
            return res;
        if (resize)
        {
            // set size first
            Vec2i newSize = size + Vec2i(dx, -dy);
            Vec2i oldSize = size;
            if (newSize.x > appw)
              newSize.x = appw;
            if (newSize.y + titlebarHeight > apph)
              newSize.y = apph - titlebarHeight;
            SetSize(newSize);
            // store the ACTUAL size difference
            Vec2i sizeDiff = oldSize - size;
            // then set position
            Vec2i newPos = position + Vec2i(0, sizeDiff.y);
            SetPos(newPos);
            return this;
        }
        else if (move)
        {
            SetPos(position + Vec2i(dx, dy));
            return this;
        }
        if (IsMouseInBody(Vec2i(x,y)) || IsMouseInTitlebar(x,y) )
            return this;
        return NULL;
    }

    Widget* Win::MouseWheel(int dir)
    {
      int x = App::I().MousePosition().x;
      int y = App::I().MousePosition().y;
      Widget *res = mainView.MouseWheel(dir);
      if (res != NULL)
          return res;
      if (IsMouseInBody(Vec2i(x,y)) || IsMouseInTitlebar(x,y) )
          return this;
      return NULL;
    }
    
    Widget* Win::KeysDown(sf::Event::KeyEvent key)
    {
        return mainView.KeysDown(key);
    }
    
    Widget* Win::KeysUp(sf::Event::KeyEvent key)
    {
        return mainView.KeysUp(key);
    }

    Widget* Win::TextEntered(char ch)
    {
        return mainView.TextEntered(ch);

    }

    View& Win::GetMainView ()
    {
        return mainView;
    }

    View& Win::AddHorizontalView (int weight)
    {
        View *nView = new View(Horizontal);
        mainView.AddWidget(nView, weight);
        return *nView;
    }

    View& Win::AddVerticalView (int weight)
    {
        View *nView = new View(Vertical);
        mainView.AddWidget(nView, weight);
        return *nView;
    }

    void Win::Draw2D()
    {
        if (movable)
        {
            // Title
            Vec2i titleSize = Vec2i(size.x, -titlebarHeight);

            glScissor(position.x, position.y + titleSize.y, titleSize.x, -titleSize.y);

            DrawBackground(position, position + size);
            DrawTitle(position, position + titleSize);

            // Text
            Vec2i textSize = Vec2i((int)title.getGlobalBounds().width, (int)title.getGlobalBounds().height);
            
            // Resize area
            // TODO: Make it dependant on "resizable" bool
            DrawQuad( Vec2i(position.x + size.x, position.y), 
                      Vec2i(position.x + size.x - resizeAreaSize, position.y - titlebarHeight),
                      resizeTexture, Vec3d(1,1,1), 255);

            SetTextPos(title,  position + (titleSize - textSize)/2);

            RenderText(title);

            glScissor(0,0,appw, apph);
        }

        mainView.Draw2D();
    }

    bool Win::Update(double dTime)
    {
        mainView.Update(dTime);
        return false;
    }

    bool Win::IsMouseInTitlebar(int x, int y)
    {
        return ( movable &&
                 x <= position.x + size.x &&
                 x >= position.x &&
                 y <= position.y &&
                 y >= position.y - titlebarHeight );
    }

    bool Win::IsMouseInResizeArea(int x, int y)
    {
        return (movable &&
                x <= position.x + size.x &&
                x >= position.x + size.x - resizeAreaSize &&
                y <= position.y &&
                y >= position.y - titlebarHeight );
    }

    void Win::OnPositionChange(Vec2i oldPosition)
    {
        if (position.y - titlebarHeight < 0)
            position.y = titlebarHeight;
        mainView.SetPos(position);
    }  

    void Win::OnSizeChange(Vec2i oldSize)
    {
        if (size.x < minSize.x)
            size.x = minSize.x;
        if (size.y < minSize.y)
            size.y = minSize.y;
        mainView.SetSize(size);
    }
    
    /*static*/ sf::Texture * Win::resizeTexture = NULL;
}